﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace QD.Data.Query
{
    public abstract class Query
    {
        public String Fields { get; private set; }
        public String Expression { get; set; }
        public String Order { get; protected set; }
        public String Group { get; protected set; }
        public static Query Empty { get { return new QueryField(); } }

        public Query SetOrder(QueryField field, SortType type)
        {
            this.Order = String.Format("{0} {1}", field == null ? "" : field.Name, type == SortType.RAND ? "RANDOM()" : type.ToString());
            return this;
        }

        public Query SetGroup(QueryField field)
        {
            this.Group = String.Format("{0}", field == null ? "" : field.Name);
            return this;
        }

        public Query SetFields(string fields)
        {
            if (!string.IsNullOrEmpty(fields))
                this.Fields = fields;
            return this;
        }

        private Query Or(Query q)
        {
            if (this.Expression != String.Empty)
                this.Expression += " OR ";

            this.Expression += " " + q.Expression;

            return this;
        }

        private Query And(Query q)
        {
            if (this.Expression != String.Empty)
                this.Expression += " AND ";

            this.Expression += " " + q.Expression;
            return this;
        }

        public Query Not(Query q)
        {
            if (this.Expression != String.Empty)
                this.Expression += " NOT ";

            this.Expression += " " + q.Expression;

            return this;
        }

        public Query Block()
        {
            if (this.Expression != String.Empty)
                this.Expression = String.Format("({0})", this.Expression);
            return this;
        }

        public Query Block(String function, params String[] parameters)
        {
            if (this.Expression != String.Empty)
                this.Expression = String.Format("{1}({0})", this.Expression, function);
            return this;
        }

        public static Query operator |(Query q1, Query q2)
        {
            if (q1 == null) return q2;
            if (q2 == null) return q1;
            return q1.Or(q2);
        }

        public static Query operator &(Query q1, Query q2)
        {
            if (q1 == null) return q2;
            if (q2 == null) return q1;
            return q1.And(q2);
        }

        public static Query operator !(Query q)
        {
            return q.Not(q);
        }

        public Query Select(QueryTable table)
        {
            this.Fields = table.Location;
            return this;
        }

        public Query Select(Query q)
        {
            throw new NotImplementedException();
        }
        public static Query ComplexSQL(String sql)
        {
            Query query = Query.Empty;
            query.Expression = sql;
            return query;
        }
    }
}
